﻿using System;
using System.IO;
using Kent.Boogaart.Gauntlet;
using Kent.Boogaart.Gauntlet.OutputGenerators;
using NUnit.Framework;

namespace Kent.Boogaart.UnitTest.Gauntlet.OutputGenerators
{
	[TestFixture]
	public sealed class NVelocityOutputGeneratorTest
	{
		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Generate_ShouldThrowIfContextIsNull()
		{
			NVelocityOutputGenerator generator = new NVelocityOutputGenerator();
			generator.Generate(null);
		}

		[Test]
		public void Generate_ShouldCreateOutputFileWithTemplateContents()
		{
			NVelocityOutputGenerator generator = new NVelocityOutputGenerator();
			FileInfo inputFile = GetTempFile();
			FileInfo templateFile = GetTempFile("here's my template");
			FileInfo outputFile = GetTempFile();
			Context context = new Context() { InputFile = inputFile, OutputFile = outputFile, TemplateFile = templateFile, Timestamp = DateTime.Now };
			generator.Generate(context);

			Assert.AreEqual("here's my template", File.ReadAllText(outputFile.FullName));
		}

		[Test]
		public void Generate_ShouldPassStateIntoTemplate()
		{
			NVelocityOutputGenerator generator = new NVelocityOutputGenerator();
			FileInfo inputFile = GetTempFile();
			FileInfo templateFile = GetTempFile("$val1 hello $val2");
			FileInfo outputFile = GetTempFile();
			Context context = new Context() { InputFile = inputFile, OutputFile = outputFile, TemplateFile = templateFile, Timestamp = DateTime.Now };
			context.State["val1"] = "first value";
			context.State["val2"] = "second value";
			generator.Generate(context);

			Assert.AreEqual("first value hello second value", File.ReadAllText(outputFile.FullName));
		}

		[Test]
		[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "The context state cannot contain a variable called 'Context' because that is used to store the generation context.")]
		public void Generate_ShouldThrowIfStateContainsVariableCalledContext()
		{
			NVelocityOutputGenerator generator = new NVelocityOutputGenerator();
			FileInfo inputFile = GetTempFile();
			FileInfo templateFile = GetTempFile();
			FileInfo outputFile = GetTempFile();
			Context context = new Context() { InputFile = inputFile, OutputFile = outputFile, TemplateFile = templateFile, Timestamp = DateTime.Now };
			context.State["Context"] = "something";
			generator.Generate(context);
		}

		[Test]
		public void Generate_ShouldPlaceContextInContextVariable()
		{
			DateTime now = DateTime.Now;

			NVelocityOutputGenerator generator = new NVelocityOutputGenerator();
			FileInfo inputFile = GetTempFile();
			FileInfo templateFile = GetTempFile("$Context.Timestamp $Context");
			FileInfo outputFile = GetTempFile();
			Context context = new Context() { InputFile = inputFile, OutputFile = outputFile, TemplateFile = templateFile, Timestamp = DateTime.Now };
			generator.Generate(context);

			Assert.AreEqual(string.Format("{0} Kent.Boogaart.Gauntlet.Context", now), File.ReadAllText(outputFile.FullName));
		}

		private static FileInfo GetTempFile()
		{
			return GetTempFile(null);
		}

		private static FileInfo GetTempFile(string contents)
		{
			string file = Path.GetTempFileName();

			if (contents != null)
			{
				using (StreamWriter streamWriter = File.CreateText(file))
				{
					streamWriter.Write(contents);
				}
			}

			return new FileInfo(file);
		}
	}
}
